---
title: Testing your providers
---

import { AutoSnippet } from "../../src/components/CodeSnippet";
import createContainer from "!!raw-loader!./testing/create_container.dart";
import unitTest from "!!raw-loader!./testing/unit_test.dart";
import widgetTest from "!!raw-loader!./testing/widget_test.dart";
import fullWidgetTest from "!!raw-loader!./testing/full_widget_test.dart";
import widgetContainerOf from "!!raw-loader!./testing/widget_container_of.dart";
import providerToMock from "./testing/provider_to_mock";
import mockProvider from "!!raw-loader!./testing/mock_provider.dart";
import autoDisposeListen from "!!raw-loader!./testing/auto_dispose_listen.dart";
import listenProvider from "!!raw-loader!./testing/listen_provider.dart";
import awaitFuture from "!!raw-loader!./testing/await_future.dart";

A core part of the Riverpod API is the ability to test your providers in isolation.

For a proper test suites, there are a few challenges to overcome:

- Tests should not share state. This means that new tests should
  not be affected by the previous tests.
- Tests should give us the ability to mock certain functionalities,
  to achieve the desired state.
- The test environment should be as close as possible to the real
  environment.

Fortunately, Riverpod makes it easy to achieve all of these goals.

## Setting up a test

When defining a test with Riverpod, there are two main scenarios:

- Unit tests, usually with no Flutter dependency.
  This can be useful for testing the behavior of a provider in isolation.
- Widget tests, usually with a Flutter dependency.
  This can be useful for behavior of a widget using a provider.

### Unit tests

Unit tests are defined using the `test` function from [package:test](https://pub.dev/packages/test).

The main difference with any other test is that we will want to create
a `ProviderContainer` object. This object will enable our test to interact
with providers.

It encouraged to make a testing utility for both creating and disposing
of a `ProviderContainer` object:

<AutoSnippet raw={createContainer} />

Then, we can define a `test` using this utility:

<AutoSnippet raw={unitTest} />

Now that we have a ProviderContainer, we can use it to read providers using:

- `container.read`, to read the current value of a provider.
- `container.listen`, to listen to a provider and be notified of changes.

:::caution
Be careful when using `container.read` when providers are automatically disposed.  
If your provider is not listened, chances are its state will get destroyed
in the middle of your test.

In that case, consider using `container.listen`.  
Its return value enables reading the current value of provider anyway,
but will also ensure that the provider is not disposed in the middle of your test:

<AutoSnippet raw={autoDisposeListen} />
:::

### Widget tests

Widget tests are defined using the `testWidgets` function from [package:flutter_test](https://pub.dev/packages/flutter_test).

In this case, the main difference with usual Widget tests is that we must add
a `ProviderScope` widget at the root of `tester.pumpWidget`:

<AutoSnippet raw={widgetTest} />

This is similar to what we do when we enable Riverpod in our Flutter app.

Then, we can use `tester` to interact with our widget.
Alternatively if you want to interact with providers, you can obtain
a `ProviderContainer`.
One can be obtained using `ProviderScope.containerOf(buildContext)`.  
By using `tester`, we can therefore write the following:

<AutoSnippet raw={widgetContainerOf} />

We can then use it to read providers. Here's a full example:

<AutoSnippet raw={fullWidgetTest} />

## Mocking providers

So far, we've seen how to setup a test and to basic interactions with providers.
However, in some cases, we may want to mock a provider.

The cool part: All providers can be mocked by default, without any additional setup.  
This is possible by specifying the `overrides` parameter on either
`ProviderScope` or `ProviderContainer`.

Consider the following provider:

<AutoSnippet {...providerToMock} />

We can mock it using:

<AutoSnippet raw={mockProvider} />

## Spying on changes in a provider

Since we obtained a `ProviderContainer` in our tests, it is possible to
use it to "listen" to a provider:

<AutoSnippet raw={listenProvider} />

You can then combine this with packages such as [mockito](https://pub.dev/packages/mockito)
or [mocktail](https://pub.dev/packages/mocktail) to use their `verify` API.  
Or more simply, you can add all changes in a list and assert on it.

## Awaiting for asynchronous providers

In Riverpod, it is very common for providers to return a Future/Stream.  
In that case, chances are our tests wants to await for that asynchronous operation
to be completed.

One way to do so is to read the `.future` of a provider:

<AutoSnippet raw={awaitFuture} />
